package com.atom.wyz.new_opengl.util;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.ETC1Util;
import android.opengl.GLES11Ext;
import android.opengl.GLES30;
import android.opengl.GLUtils;
import android.util.Log;
import android.view.View;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.microedition.khronos.opengles.GL10;

public final class TextureUtil {

    public static int getTextureId(View view, Integer id, String path, boolean isMipmap) {
        int[] textureArray = new int[1];
        GLES30.glGenTextures(1, textureArray, 0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureArray[0]);
        if (isMipmap) {
            GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR_MIPMAP_LINEAR);
            GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR_MIPMAP_NEAREST);
        } else {
            GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
            GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
        }
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_MIRRORED_REPEAT);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_MIRRORED_REPEAT);

        textureCompression(view, 1, id, path);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);

        return textureArray[0];
    }

    public static int get3DTextureId(View view, int[] resourceIds) {
        int[] textureArray = new int[1];
        GLES30.glGenTextures(1, textureArray, 0);
        int cubeMapTextureId = textureArray[0];
        //绑定纹理
        GLES30.glBindTexture(GLES30.GL_TEXTURE_CUBE_MAP, cubeMapTextureId);
        //设置纹理采样方式、拉伸方式
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_CUBE_MAP, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_CUBE_MAP, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_CUBE_MAP, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_CUBE_MAP, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);
        //循环加载立方图纹理各个面的图片
        for (int face = 0; face < 6; face++) {
            InputStream is = view.getResources().openRawResource(resourceIds[face]);
            Bitmap bitmap;
            try {
                bitmap = BitmapFactory.decodeStream(is);
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    Log.e("CubeMap", "Could not decode texture for face " + Integer.toString(face));
                }
            }
            //加载立方图纹理中的指定编号的面
            GLUtils.texImage2D(GLES30.GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0,bitmap, 0);
            bitmap.recycle();
        }
        return cubeMapTextureId;

    }


    public static void textureCompression(View view, int mode, int id, String path) {
        switch (mode) {
            case 1:
                Bitmap bitmap = BitmapFactory.decodeResource(view.getResources(), id);
                GLUtils.texImage2D(GLES30.GL_TEXTURE_2D,
                        0,
                        bitmap,
                        0);
                bitmap.recycle();
                break;
            case 2:
                try {
                    InputStream open = view.getResources().getAssets().open(path);
                    ETC1Util.loadTexture(
                            GLES30.GL_TEXTURE_2D,
                            0,
                            0,
                            GLES30.GL_RGB,
                            GLES30.GL_UNSIGNED_BYTE,
                            open
                    );
                } catch (IOException e) {
                    e.printStackTrace();
                }

                break;
            case 3:
                try {
                    bitmap = BitmapFactory.decodeResource(view.getResources(), id);
                    ETC1Util.loadTexture(
                            GLES30.GL_TEXTURE_2D,
                            0,
                            0,
                            GLES30.GL_RGB,
                            GLES30.GL_UNSIGNED_BYTE,
                            Bitmap2IS(bitmap)
                    );
                    bitmap.recycle();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case 4:
                byte[] bytes = loadDataFromAssets(view.getResources(), path);
                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bytes.length).order(ByteOrder.LITTLE_ENDIAN);
                byteBuffer.put(bytes).position(16);
                ByteBuffer headerBuffer = ByteBuffer.allocateDirect(16).order(ByteOrder.BIG_ENDIAN);
                headerBuffer.put(bytes, 0, 16).position(0);
                int width = headerBuffer.getShort(12);
                int height = headerBuffer.getShort(14);
                GLES30.glCompressedTexImage2D(
                        GLES30.GL_TEXTURE_2D,
                        0,
                        GLES30.GL_COMPRESSED_RGBA8_ETC2_EAC,
                        width,
                        height,
                        0,
                        bytes.length - 16,
                        byteBuffer);
                break;
            case 5:
                break;
        }
    }

    private static InputStream Bitmap2IS(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        InputStream sbs = new ByteArrayInputStream(baos.toByteArray());
        return sbs;
    }

    private static byte[] loadDataFromAssets(Resources r, String fname) {
        byte[] data = null;
        InputStream in = null;
        try {
            in = r.getAssets().open(fname);
            int ch = 0;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((ch = in.read()) != -1) {
                baos.write(ch);
            }
            data = baos.toByteArray();
            baos.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return data;
    }

    public static int createTextureID(boolean isOes) {
        int target = GLES30.GL_TEXTURE_2D;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
            target = isOes ? GLES11Ext.GL_TEXTURE_EXTERNAL_OES : GLES30.GL_TEXTURE_2D;
        }
        int[] texture = new int[1];
        GLES30.glGenTextures(1, texture, 0);
        GLES30.glBindTexture(target, texture[0]);
        GLES30.glTexParameterf(target,
                GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
        GLES30.glTexParameterf(target,
                GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
        GLES30.glTexParameteri(target,
                GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameteri(target,
                GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
        return texture[0];
    }

    public static int initTextureRepeat(int drawableId , Resources res){

        int[] textures = new int[1];
        GLES30.glGenTextures
                (
                        1,
                        textures,
                        0
                );
        int textureId = textures[0];
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);


        InputStream is = res.openRawResource(drawableId);
        Bitmap bitmapTmp;
        try {
            bitmapTmp = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }



        GLUtils.texImage2D
                (
                        GLES30.GL_TEXTURE_2D,
                        0,
                        bitmapTmp,
                        0
                );
        bitmapTmp.recycle();

        return textureId;
    }

    public static int initTextureDefault(int drawableId , Resources res) {

        int[] textures = new int[1];
        GLES30.glGenTextures
                (
                        1,
                        textures,
                        0
                );
        int textureId = textures[0];
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);


        InputStream is = res.openRawResource(drawableId);
        Bitmap bitmapTmp;
        try {
            bitmapTmp = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        GLUtils.texImage2D
                (
                        GLES30.GL_TEXTURE_2D,
                        0,
                        bitmapTmp,
                        0
                );
        bitmapTmp.recycle();

        return textureId;
    }

}
